package com.zshan.clinic.admin.service.medical;


import com.zshan.clinic.admin.constant.Constants;
import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.admin.mapper.medical.SpecClinicFollowupMapper;
import com.zshan.clinic.admin.service.clinic.ClinicEmpService;
import com.zshan.clinic.admin.service.config.ProjectFeeService;
import com.zshan.clinic.admin.service.notice.ClinicNoticeService;
import com.zshan.clinic.admin.task.AsyncTaskService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.enums.FollowUpChannelEnum;
import com.zshan.clinic.common.enums.FollowUpStatusEnum;
import com.zshan.clinic.common.enums.YesOrNoEnum;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.date.DateTimeUtils;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.database.dao.ClinicFollowupMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 门诊随访
 * @author lichen
 */
@Service
@Slf4j
public class ClinicFollowupService {

    @Autowired
    private ClinicFollowupMapper clinicFollowupMapper;

    @Autowired
    private SpecClinicFollowupMapper specClinicFollowupMapper;

    @Autowired
    private ProjectFeeService projectFeeService;

    @Autowired
    private ClinicEmpService clinicEmpService;

    @Autowired
    private ClinicNoticeService noticeService;

    @Autowired
    private AsyncTaskService asyncTaskService;

    /**
     * 查询患者随访记录
     * @param clinicId
     * @param patientId
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<ClinicFollowupPatientVo> getPatientFollowupList(Long clinicId, Long patientId, LocalDate visitDate, Integer pageNo, Integer pageSize) {
        Long totalCount = specClinicFollowupMapper.getPatientMedicalCount(clinicId,patientId,visitDate);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<ClinicFollowupPatientVo> followupList = specClinicFollowupMapper.getPatientMedicalList(clinicId,patientId,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,followupList);
    }

    /**
     * 查询今日待随访数
     * @param clinicId
     * @param doctorId
     * @return
     */
    public Long getFollowupPendingCount(Long clinicId, Long doctorId) {
        //医生助理也能看医生的数据
        List<Long> doctorList = new ArrayList<>();
        doctorList.add(doctorId);
        doctorList.addAll(projectFeeService.getDoctorListByAssistantId(doctorId));
        ClinicFollowupExample example = new ClinicFollowupExample();
        ClinicFollowupExample.Criteria criteria = example.createCriteria();
        criteria.andVisitDateEqualTo(LocalDate.now());
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andDoctorIdIn(doctorList);
        criteria.andFollowupStatusEqualTo(FollowUpStatusEnum.PENDING.getValue());
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return clinicFollowupMapper.countByExample(example);
    }
    /**
     * 查询患者随访历史
     * @param clinicId
     * @param patientId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<ClinicFollowupRecordVo> getRecordList(Long clinicId,Long patientId, Integer pageNo, Integer pageSize){
        return specClinicFollowupMapper.getRecordList(clinicId,patientId,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }

    /**
     * 查询随访列表
     * @param clinicId
     * @param doctorId
     * @param patientName
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<ClinicFollowupPageVo> getFollowupList(Long clinicId, Long doctorId, String patientName, LocalDate followupDate, Integer pageNo, Integer pageSize){
        if(followupDate == null){
            followupDate = LocalDate.now();
        }
        //医生助理也能看医生的数据
        List<Long> doctorList = new ArrayList<>();
        doctorList.add(doctorId);
        doctorList.addAll(projectFeeService.getDoctorListByAssistantId(doctorId));
        return specClinicFollowupMapper.getFollowupList(clinicId,doctorList,patientName,followupDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }

    /**
     * 查询随访详情
     * @param clinicId
     * @param followupId
     * @return
     */
    public ClinicFollowupDetailVo getFollowupDetail(Long clinicId,Long followupId){
        return specClinicFollowupMapper.getFollowupDetail(clinicId,followupId);
    }



    /**
     * 分页查询门诊随访
     * @param patientName 患者姓名（模糊搜索）
     * @param pageNo 页码
     * @param pageSize 每页数量
     * @return 分页结果
     */
    public PageInfo<ClinicFollowup> getFollowupListByCondition(String patientName, Integer pageNo, Integer pageSize) {
        ClinicFollowupExample example = new ClinicFollowupExample();
        ClinicFollowupExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(patientName)) {
            criteria.andPatientNameLike("%" + patientName + "%");
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = clinicFollowupMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }
        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<ClinicFollowup> followupList = clinicFollowupMapper.selectByExample(example);
        return new PageInfo<>(totalCount, followupList);
    }

    /**
     * 完成诊断以后，根据是否需要随访添加
     * @param clinicMedical
     */
    @Transactional(rollbackFor = Exception.class)
    public void addFollowup(ClinicMedicalDetailVo clinicMedical,Long updateUserId,String updateBy) {
        ClinicFollowup dbClinicFollowup = getClinicFollowupByMedicalId(clinicMedical.getMedicalId());
        if(dbClinicFollowup != null){
            log.info("已经添加了随访记录，门诊ID:{}",clinicMedical.getMedicalId());
            return;
        }
        ClinicFollowup clinicFollowup = new ClinicFollowup();
        clinicFollowup.setPatientPhone(clinicMedical.getPatientPhone());
        clinicFollowup.setIdCard(clinicMedical.getIdCard());
        clinicFollowup.setFollowupDate(DateTimeUtils.addDays(clinicMedical.getVisitDate(),clinicMedical.getFollowUpDays()));
        clinicFollowup.setMedicalId(clinicMedical.getMedicalId());
        clinicFollowup.setVisitNo(clinicMedical.getVisitNo());
        clinicFollowup.setVisitDate(clinicMedical.getVisitDate());
        clinicFollowup.setDoctorId(clinicMedical.getDoctorId());
        clinicFollowup.setDoctorName(clinicMedical.getDoctorName());
        clinicFollowup.setPatientId(clinicMedical.getPatientId());
        clinicFollowup.setPatientName(clinicMedical.getPatientName());
        clinicFollowup.setPatientGender(clinicMedical.getPatientGender());
        clinicFollowup.setComplaint(clinicMedical.getComplaint());
        clinicFollowup.setDiagnosis(clinicMedical.getDiagnosis());
        clinicFollowup.setDiagnosisTime(clinicMedical.getDiagnosisTime());
        clinicFollowup.setFollowupStatus(FollowUpStatusEnum.PENDING.getValue());
        clinicFollowup.setClinicId(clinicMedical.getClinicId());
        clinicFollowup.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicFollowup.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicFollowup.setCreateUserId(updateUserId);
        clinicFollowup.setCreateBy(updateBy);
        clinicFollowup.setCreateTime(new Date());
        clinicFollowupMapper.insertSelective(clinicFollowup);
    }

    public ClinicFollowup getClinicFollowupByMedicalId(Long medicalId) {
        ClinicFollowupExample example = new ClinicFollowupExample();
        ClinicFollowupExample.Criteria criteria = example.createCriteria();
        criteria.andMedicalIdEqualTo(medicalId);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<ClinicFollowup> clinicFollowupList = clinicFollowupMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(clinicFollowupList)){
            return null;
        }
        return clinicFollowupList.get(0);
    }


    /**
     * 校验门诊随访
     * @param followup 实体
     */
    public void validateFollowup(ClinicFollowup followup) {
        if (StringUtils.isBlank(followup.getFollowupChannel())) {
            throw new BusinessFailException("随访渠道不能为空");
        }
        if(!FollowUpChannelEnum.isValue(followup.getFollowupChannel())){
            throw new BusinessFailException("随访渠道错误");
        }
        if(followup.getRealFollowupDate() == null){
            throw new BusinessFailException("随访时间不能为空");
        }
        ClinicEmp clinicEmp = clinicEmpService.getEnabledEmpById(followup.getFollowupEmpId());
        if(clinicEmp == null){
            throw new BusinessFailException("随访人不存在");
        }
        followup.setFollowupEmpName(clinicEmp.getEmpName());
        if(StringUtil.isBlank(followup.getFollowupResult())){
            throw new BusinessFailException("随访结果不能为空");
        }
    }

    /**
     * 根据主键查询门诊随访
     * @param followupId 主键ID
     * @return 实体
     */
    public ClinicFollowup getFollowupById(Long followupId) {
        if (followupId == null) {
            return null;
        }
        ClinicFollowup followup = clinicFollowupMapper.selectByPrimaryKey(followupId);
        if (followup == null || YesOrNoEnum.YES.getValue().equals(followup.getIsDelete())) {
            return null;
        }
        return followup;
    }

    /**
     * 修改门诊随访
     * @param followup 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void completeFollowup(ClinicFollowup followup) {
        validateFollowup(followup);
        ClinicFollowup dbFollowup = getFollowupById(followup.getFollowupId());
        if (dbFollowup == null) {
            throw new BusinessFailException("随访记录不存在");
        }
        dbFollowup.setFollowupStatus(FollowUpStatusEnum.COMPLETED.getValue());
        dbFollowup.setFollowupChannel(followup.getFollowupChannel());
        dbFollowup.setRealFollowupDate(followup.getRealFollowupDate());
        dbFollowup.setFollowupEmpId(followup.getFollowupEmpId());
        dbFollowup.setFollowupEmpName(followup.getFollowupEmpName());
        dbFollowup.setFollowupResult(followup.getFollowupResult());
        dbFollowup.setAttachmentUrls(followup.getAttachmentUrls());
        dbFollowup.setOperatorUserId(followup.getUpdateUserId());
        dbFollowup.setOperatorBy(followup.getUpdateBy());
        dbFollowup.setOperateTime(new Date());
        dbFollowup.setUpdateUserId(followup.getUpdateUserId());
        dbFollowup.setUpdateBy(followup.getUpdateBy());
        dbFollowup.setUpdateTime(new Date());
        clinicFollowupMapper.updateByPrimaryKeySelective(dbFollowup);
        //统计诊所今日营收
        StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
        statClinicIncomeDaily.setClinicId(dbFollowup.getClinicId());
        statClinicIncomeDaily.setFollowupCount(CommonConstant.DEFAULT_1);
        asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
    }

    /**
     * 删除门诊随访（逻辑删除）
     * @param followup 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteFollowup(ClinicFollowup followup) {
        ClinicFollowup dbFollowup = getFollowupById(followup.getFollowupId());
        if (dbFollowup == null) {
            throw new BusinessFailException("随访记录不存在");
        }
        dbFollowup.setIsDelete(YesOrNoEnum.YES.getValue());
        dbFollowup.setUpdateUserId(followup.getUpdateUserId());
        dbFollowup.setUpdateBy(followup.getUpdateBy());
        dbFollowup.setUpdateTime(new Date());
        clinicFollowupMapper.updateByPrimaryKeySelective(dbFollowup);
    }

    /**
     * 发送随访提醒
     * @param followupDate
     */
    public void followupReminder(LocalDate followupDate) {
        List<UnFollowupVo> unFollowupList = specClinicFollowupMapper.getUnFollowupList(followupDate);
        if(CollectionUtils.isEmpty(unFollowupList)){
            return;
        }
        for(UnFollowupVo unFollowupVo : unFollowupList){
            ClinicNotice clinicNotice = new ClinicNotice();
            clinicNotice.setEmpId(unFollowupVo.getDoctorId());
            clinicNotice.setNoticeName(Constants.NOTICE_NAME_UNFOLLOWUP);
            clinicNotice.setNoticeContent(String.format(Constants.NOTICE_CONTENT_UNFOLLOWUP,unFollowupVo.getUnFollowupCount()));
            clinicNotice.setClinicId(unFollowupVo.getClinicId());
            noticeService.addNotice(clinicNotice);
        }
    }
}
